<template>
  <div class="stress-test-container">
    <el-row :gutter="20">
      <!-- 左侧控制面板 -->
      <el-col :xs="24" :sm="24" :md="10" :lg="10" :xl="10">
        <el-card class="control-panel">
          <template #header>
            <div class="card-header">
              <h3>压力测试控制面板</h3>
              <el-tag :type="isConnected ? 'success' : 'danger'" size="small">
                {{ isConnected ? '主控端已连接' : '主控端已连接' }}
              </el-tag>
            </div>
          </template>
          
          <div class="form-container">
            <el-form :model="form" label-width="100px">
              <!-- 测试类型选择 -->
            <el-form-item label="测试类型">
                <el-radio-group v-model="form.testType" @change="handleTestTypeChange">
                  <el-radio-button label="layer4">Layer4 攻击</el-radio-button>
                  <el-radio-button label="layer7">Layer7 攻击</el-radio-button>
              </el-radio-group>
            </el-form-item>

              <!-- Layer4 攻击配置 -->
              <template v-if="form.testType === 'layer4'">
              <el-form-item label="攻击类型">
                  <el-select v-model="form.layer4Type" class="w-full" @change="handleAttackTypeChange">
                    <el-option
                      v-for="item in layer4Types"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    >
                      <div class="attack-option">
                        <span>{{ item.label }}</span>
                        <el-tag size="small" type="warning" v-if="item.needPort">需要端口</el-tag>
                      </div>
                    </el-option>
                </el-select>
              </el-form-item>

                <el-form-item label="目标地址">
                  <el-input v-model="form.targetIp" placeholder="请输入目标IP地址">
                    <template #append v-if="currentAttackInfo?.needPort">
                      <el-input 
                        v-model="form.port" 
                        placeholder="端口" 
                        style="width: 80px"
                        @focus="handlePortFocus"
                      >
                        <template #suffix v-if="currentAttackInfo.defaultPort">
                          <el-tooltip 
                            :content="`默认端口: ${currentAttackInfo.defaultPort}`"
                            placement="top"
                          >
                            <el-icon class="cursor-pointer" @click="useDefaultPort">
                              <InfoFilled />
                            </el-icon>
                          </el-tooltip>
              </template>
                      </el-input>
            </template>
                  </el-input>
              </el-form-item>
            </template>
            
              <!-- Layer7 攻击配置 -->
              <template v-if="form.testType === 'layer7'">
                <el-form-item label="攻击类型" prop="layer7Type">
                  <el-select v-model="form.layer7Type" placeholder="请选择攻击类型" class="w-full" @change="handleAttackTypeChange">
                    <el-option 
                      v-for="item in layer7Types" 
                      :key="item.value" 
                      :label="item.label" 
                      :value="item.value"
                    />
                </el-select>
              </el-form-item>

              <el-form-item label="目标URL" prop="targetUrl">
                <el-input v-model="form.targetUrl" placeholder="请输入目标URL" />
                </el-form-item>

                <!-- 代理配置 -->
                <el-form-item label="代理IP池">
                  <el-upload
                    class="upload-demo"
                    action="#"
                    :auto-upload="false"
                    :on-change="handleProxyFileChange"
                    accept=".txt"
                  >
                    <template #trigger>
                      <el-button type="primary">选择代理文件</el-button>
              </template>
                    <template #tip>
                      <div class="el-upload__tip">
                        请上传txt格式的代理IP列表文件，每行一个代理地址
                      </div>
                    </template>
                  </el-upload>
                  <div v-if="form.proxyList.length" class="mt-2">
                    已加载 {{ form.proxyList.length }} 个代理IP
                  </div>
              </el-form-item>
            </template>

            <!-- 通用配置 -->
              <el-form-item label="并发用户">
                <el-input-number v-model="form.concurrentUsers" :min="1" :max="10000" />
            </el-form-item>
            
            <el-form-item label="持续时间">
                <el-input-number v-model="form.duration" :min="1" :max="3600">
                  <template #append>秒</template>
                </el-input-number>
            </el-form-item>
            
              <!-- 控制按钮 -->
            <el-form-item>
                <el-button type="primary" @click="startTest" :loading="testing">
                {{ testing ? '测试中...' : '开始测试' }}
              </el-button>
                <el-button @click="stopTest" :disabled="!testing">停止测试</el-button>
            </el-form-item>
          </el-form>
          </div>
        </el-card>
      </el-col>

      <!-- 右侧攻击说明 -->
      <el-col :xs="24" :sm="24" :md="14" :lg="14" :xl="14" class="mt-4 md:mt-0">
        <el-card class="info-panel" v-if="currentAttackInfo">
          <template #header>
            <div class="card-header">
              <h3>{{ currentAttackInfo.name }}</h3>
              <el-tag size="small" :type="currentAttackInfo.needPort ? 'warning' : 'info'">
                {{ currentAttackInfo.needPort ? '需要指定端口' : '无需端口' }}
              </el-tag>
            </div>
          </template>

          <div class="attack-info">
            <!-- 使用场景 -->
            <div class="info-section">
              <h4>
                <el-icon><Aim /></el-icon>
                使用场景
              </h4>
              <div class="scene-tags">
                <el-tag
                  v-for="(scene, index) in currentAttackInfo.scenes"
                  :key="index"
                  size="small"
                  class="scene-tag"
                >
                  {{ scene }}
                </el-tag>
                </div>
                </div>

            <!-- 攻击特点 -->
            <div class="info-section">
              <h4>
                <el-icon><Star /></el-icon>
                攻击特点
              </h4>
              <ul class="feature-list">
                <li v-for="(feature, index) in currentAttackInfo.features" :key="index">
                  {{ feature }}
                </li>
              </ul>
            </div>

            <!-- 注意事项 -->
            <div class="info-section">
              <h4>
                <el-icon><Warning /></el-icon>
                注意事项
              </h4>
              <ul class="warning-list">
                <li v-for="(note, index) in currentAttackInfo.notes" :key="index">
                  {{ note }}
                </li>
              </ul>
            </div>

            <!-- 最佳实践 -->
            <div class="info-section">
              <h4>
                <el-icon><Guide /></el-icon>
                最佳实践
              </h4>
              
              <!-- Layer4最佳端口 -->
              <template v-if="form.testType === 'layer4'">
                <div class="best-ports">
                  <h5>推荐测试端口:</h5>
                  <div class="port-tags">
                    <el-tag
                      v-for="port in currentAttackInfo.bestPractices.ports"
                      :key="port"
                      size="small"
                      class="port-tag"
                      @click="usePort(port)"
                    >
                      {{ port }}
                    </el-tag>
                  </div>
                </div>
              </template>

              <!-- Layer7目标建议 -->
              <template v-else>
                <div class="best-targets">
                  <h5>推荐测试目标:</h5>
                  <ul class="target-list">
                    <li v-for="target in currentAttackInfo.bestPractices.targets" :key="target">
                      {{ target }}
                    </li>
                  </ul>
                </div>
              </template>

              <div class="practice-desc">
                {{ currentAttackInfo.bestPractices.description }}
              </div>
            </div>

            <!-- 防护绕过建议 -->
            <div class="info-section">
              <h4>
                <el-icon><Lock /></el-icon>
                防护绕过建议
              </h4>
              <ul class="bypass-list">
                <li v-for="(tip, index) in currentAttackInfo.bestPractices.bypassProtection" :key="index">
                  {{ tip }}
                </li>
              </ul>
            </div>

            <!-- Layer7专属: 推荐请求头 -->
            <div class="info-section" v-if="form.testType === 'layer7' && currentAttackInfo.bestPractices.headers">
              <h4>
                <el-icon><Document /></el-icon>
                推荐请求头
              </h4>
              <div class="headers-preview">
                <pre><code>{{ JSON.stringify(currentAttackInfo.bestPractices.headers, null, 2) }}</code></pre>
              </div>
            </div>

            <!-- 攻击效果预览 -->
            <div class="info-section" v-if="currentAttackInfo">
              <h4>
                <el-icon><TrendCharts /></el-icon>
                攻击效果预览
              </h4>
              <el-descriptions :column="2" border>
                <el-descriptions-item label="资源消耗">
                  <el-rate 
                    v-model="currentAttackInfo.effectiveness.resourceConsumption"
                    disabled
                    show-score
                  />
                </el-descriptions-item>
                <el-descriptions-item label="绕过难度">
                  <el-rate
                    v-model="currentAttackInfo.effectiveness.bypassDifficulty"
                    disabled
                    show-score
                  />
                </el-descriptions-item>
                <el-descriptions-item label="检测难度">
                  <el-rate
                    v-model="currentAttackInfo.effectiveness.detectionDifficulty"
                    disabled
                    show-score
                  />
                </el-descriptions-item>
                <el-descriptions-item label="综合效果">
                  <el-rate
                    v-model="currentAttackInfo.effectiveness.overall"
                    disabled
                    show-score
                  />
                </el-descriptions-item>
              </el-descriptions>
                  </div>
                </div>
              </el-card>
        <el-empty v-else description="请选择攻击类型查看详细说明" />
            </el-col>
          </el-row>

    <!-- 统计卡片区域 -->
    <div class="status-cards mt-4">
      <el-card class="status-card" shadow="hover">
        <div class="status-value">
          <span class="success">{{ getOnlineCount() }}</span>
          <span class="text-gray">/</span>
          <span>{{ getTotalCount() }}</span>
        </div>
        <div class="status-label">节点</div>
      </el-card>
      <el-card class="status-card" shadow="hover">
        <div class="status-value">{{ totalTraffic }}</div>
        <div class="status-label">总流量</div>
      </el-card>
      <el-card class="status-card" shadow="hover">
        <div class="status-value">{{ totalRequests }}</div>
        <div class="status-label">总请求数</div>
      </el-card>
      <el-card class="status-card" shadow="hover">
        <div class="status-value">{{ avgLatency }}ms</div>
        <div class="status-label">平均延迟</div>
      </el-card>
    </div>

    <!-- 节点列表卡片 -->
    <el-card class="mt-4">
      <!-- 工作节点列表 -->
                <el-table
        v-loading="loading"
        :data="onlineWorkers"
        class="worker-table"
                  @selection-change="handleWorkerSelection"
        :row-key="(row) => row.ip"
        ref="tableRef"
        :max-height="400"
        style="width: 100%"
      >
        <el-table-column 
          type="selection" 
          width="60"
          :reserve-selection="true"
        />
        <el-table-column prop="ip" label="节点IP" width="160" />
              <el-table-column prop="status" label="状态" width="100">
          <template #default="{ row }">
            <el-tag :type="getStatusType(row.status)">
              {{ row.status === 'online' ? '在线' : 
                 row.status === 'busy' ? '忙碌' : '离线' }}
                  </el-tag>
                </template>
              </el-table-column>
        <el-table-column prop="os" label="系统" width="125">
                    <template #default="{ row }">
            <el-tag size="small" type="info">
              {{ row.os || '-' }}/{{ row.arch || '-' }}
            </el-tag>
                </template>
              </el-table-column>
        <el-table-column prop="cpu_cores" label="CPU核心" width="100">
          <template #default="{ row }">
            {{ row.cpu_cores || '-' }} 核
                </template>
              </el-table-column>
        <el-table-column prop="mem_total" label="内存总量" width="120">
          <template #default="{ row }">
            {{ formatBytes(row.mem_total) }}
                </template>
              </el-table-column>
        <el-table-column prop="cpuUsage" label="CPU使用率" width="150">
          <template #default="{ row }">
                        <el-progress 
              :percentage="Math.round(row.cpuUsage)" 
                          :status="getCPUStatus(row.cpuUsage)"
              :show-text="true"
              :stroke-width="18"
              text-inside
              class="progress-bar"
            >
              <span class="progress-text">{{ Math.round(row.cpuUsage) }}%</span>
            </el-progress>
                    </template>
                  </el-table-column>
        <el-table-column prop="memUsage" label="内存使用率" width="150">
                    <template #default="{ row }">
                        <el-progress 
              :percentage="Math.round(row.memUsage)"
                          :status="getMemStatus(row.memUsage)"
              :show-text="true"
              :stroke-width="18"
              text-inside
              class="progress-bar"
            >
              <span class="progress-text">{{ Math.round(row.memUsage) }}%</span>
            </el-progress>
          </template>
        </el-table-column>
        <el-table-column label="攻击统计" width="200">
          <template #default="{ row }">
            <div class="attack-stats">
              <div>请求: {{ row.attack_stats?.requests_sent || 0 }}</div>
              <div>成功: {{ row.attack_stats?.success_count || 0 }}</div>
              <div>失败: {{ row.attack_stats?.fail_count || 0 }}</div>
              <div>平均延迟: {{ row.attack_stats?.avg_latency?.toFixed(2) || 0 }}ms</div>
          </div>
          </template>
        </el-table-column>
        <el-table-column label="流量统计" width="180">
          <template #default="{ row }">
            <div class="traffic-stats">
              <div>发送: {{ formatBytes(row.attack_stats?.bytes_sent || 0) }}</div>
              <div>接收: {{ formatBytes(row.attack_stats?.bytes_received || 0) }}</div>
                </div>
                    </template>
                  </el-table-column>
                  <el-table-column prop="latency" label="延迟" width="100">
                    <template #default="{ row }">
            {{ row.latency }}ms
                    </template>
                  </el-table-column>
        <el-table-column prop="version" label="版本" width="100">
                    <template #default="{ row }">
            <el-tag size="small" type="success">
              {{ row.version || '-' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="lastHeartbeat" label="最后心跳" min-width="180">
          <template #default="{ row }">
            {{ formatTimestamp(row.lastHeartbeat) }}
                    </template>
                  </el-table-column>
                </el-table>
        </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import { Refresh, InfoFilled, Guide, Lock, Document, TrendCharts } from '@element-plus/icons-vue'
import VChart from 'vue-echarts'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart } from 'echarts/charts'
import {
  GridComponent,
  TooltipComponent,
  LegendComponent,
  TitleComponent
} from 'echarts/components'
import { getRefreshToken } from '@/utils/auth'
import { formatDate, formatDateTime } from '@/utils/formatTime'

// 注册ECharts组件
use([
  CanvasRenderer,
  LineChart,
  GridComponent,
  TooltipComponent,
  LegendComponent,
  TitleComponent
])

// 状态定义
const isConnected = ref(false)
const testing = ref(false)
const refreshing = ref(false)
const socket = ref<WebSocket | null>(null)
const reconnectTimer = ref<number | null>(null)
const allWorkers = ref<WorkerInfo[]>([])
const onlineWorkers = ref<WorkerInfo[]>([])

// 表单数据
interface FormState {
  testType: string
  targetIp: string
  targetUrl: string
  layer4Type: string
  layer7Type: string
  port: string
  concurrentUsers: number
  duration: number
  interval: number
  workerNodes: string[]
  proxyList: string[]
}

const form = reactive<FormState>({
  testType: 'layer4',
  targetIp: '',
  targetUrl: '',
  layer4Type: 'syn_flood',
  layer7Type: 'http_flood',
  port: '',
  concurrentUsers: 100,
  duration: 60,
  interval: 100,
  workerNodes: [],
  proxyList: []
})

// 性能数据
const timePoints = ref<string[]>([])
const cpuData = ref<Record<string, number[]>>({})
const memData = ref<Record<string, number[]>>({})

// 添加 WorkerInfo 类型定义
interface WorkerInfo {
  ip: string
  status: string
  cpuUsage: number
  memUsage: number
  latency: number
  lastHeartbeat: number
  traffic: number
  requests: number
  os?: string
  arch?: string
  cpu_cores?: number
  mem_total?: number
  version?: string
  selected?: boolean
  attack_stats?: {
    requests_sent: number
    bytes_sent: number
    bytes_received: number
    success_count: number
    fail_count: number
    avg_latency: number
  }
}

// 添加状态数据定义
const stats = ref({
  totalRequests: 0,
  totalTraffic: 0,
  avgLatency: 0,
  successRate: 0
})

const totalTraffic = ref(0)
const workerTraffic = ref<Array<{
  ip: string
  traffic: number
  speed: number
  packets: number
}>>([])

const trafficData = ref<Record<string, number[]>>({})

// 节点相关数据
const workerCount = ref(0) // 总节点数
const loading = ref(false)
const totalRequests = ref(0)
const avgLatency = ref(0)

// WebSocket连接管理
const initWebSocket = () => {
  try {
    if (socket.value?.readyState === WebSocket.OPEN) {
      return
    }
    
    const wsUrl = `wss://apiv2.jstzicp.top/weiyi/osdd/ws?token=${getRefreshToken()}`
    socket.value = new WebSocket(wsUrl)
    
    socket.value.onopen = () => {
      console.log('WebSocket连接已建立')
      isConnected.value = true
      // 连接建立后，主动请求节点列表
      requestWorkerList()
      if (reconnectTimer.value) {
        clearTimeout(reconnectTimer.value)
        reconnectTimer.value = null
      }
    }
    
    socket.value.onclose = () => {
      console.log('WebSocket连接已关闭')
      isConnected.value = false
      reconnectTimer.value = window.setTimeout(() => {
        console.log('尝试重新连接...')
        initWebSocket()
      }, 3000)
    }
    
    socket.value.onerror = (error) => {
      console.error('WebSocket错误:', error)
      isConnected.value = false
    }
    
    socket.value.onmessage = handleMessage
  } catch (error) {
    console.error('初始化WebSocket失败:', error)
  }
}

// 添加主动请求节点列表的方法
const requestWorkerList = () => {
  if (socket.value?.readyState === WebSocket.OPEN) {
    sendWSMessage('get_workers', {})
  }
}

// 组件引用
const tableRef = ref()

// 处理WebSocket消息
const handleMessage = (event: MessageEvent) => {
    const message = JSON.parse(event.data)
    
    switch (message.type) {
      case 'workers':
      // 转换节点数据格式
      onlineWorkers.value = Object.entries(message.data).map(([ip, data]: [string, any]) => ({
        ip,
        status: data.status || 'offline',
        cpuUsage: data.cpuUsage || 0,
        memUsage: data.memUsage || 0,
        latency: data.latency || 0,
        traffic: data.traffic || 0,
        requests: data.requests || 0,
        lastHeartbeat: data.lastHeartbeat,
        os: data.os,
        arch: data.arch,
        cpu_cores: data.cpu_cores,
        mem_total: data.mem_total,
        version: data.version,
        attack_stats: data.attack_stats
      }))
        break

      case 'worker_status':
      const workerIndex = onlineWorkers.value.findIndex(w => w.ip === message.data.ip)
      if (workerIndex > -1) {
        onlineWorkers.value[workerIndex] = {
          ...onlineWorkers.value[workerIndex],
          ...message.data,
          attack_stats: message.data.attack_stats
        }
      } else {
        onlineWorkers.value.push({
          ...message.data,
          attack_stats: message.data.attack_stats
        })
      }
      updateStats()
      break
    case 'traffic_stats': // 添加流量统计处理
      updateTrafficStats(message.data)
        break
      case 'testStopped':
        handleTestStopped()
        break
      case 'error':
        ElMessage.error(message.data)
        break
  }
}

// 处理测试停止
const handleTestStopped = () => {
  testing.value = false
  ElMessage.success('测试已停止')
}

// 开始攻击前的验证
const validateAttackParams = () => {
  if (!form.workerNodes.length) {
    ElMessage.error('请至少选择一个工作节点')
    return false
  }

  if (form.testType === 'layer4') {
    if (!form.targetIp) {
      ElMessage.error('请输入目标IP地址')
      return false
    }
    if (currentAttackInfo.value?.needPort && !form.port) {
      ElMessage.error('请输入目标端口')
      return false
    }
  } else {
    if (!form.targetUrl) {
      ElMessage.error('请输入目标URL')
      return false
    }
    if (!form.proxyList.length) {
      ElMessage.warning('建议配置代理IP以提高测试效果')
    }
  }

  return true
}

// 修改开始测试方法
const startTest = async () => {
  if (!socket.value || socket.value.readyState !== WebSocket.OPEN) {
    ElMessage.error('WebSocket连接未建立,请稍后重试')
    return
  }

  if (!form.workerNodes.length) {
    ElMessage.error('请选择至少一个节点')
    return
  }
  
  if (!form.targetUrl) {
    ElMessage.error('请输入目标URL')
    return
  }

  try {
    const message = {
      type: 'startTest',
      data: {
        testType: form.testType,
        targetUrl: form.targetUrl,
        workerNodes: form.workerNodes,
        ccType: form.ccType,
        concurrentUsers: form.concurrentUsers,
        duration: form.duration,
        interval: form.interval
      }
    }

    // 确保WebSocket连接已建立
    if (socket.value && socket.value.readyState === WebSocket.OPEN) {
      socket.value.send(JSON.stringify(message))
      ElMessage.success('已发送测试命令')
    } else {
      ElMessage.error('WebSocket连接已断开,请刷新页面重试')
    }
  } catch (error) {
    ElMessage.error('发送测试命令失败: ' + (error.message || '未知错误'))
  }
}

// 停止测试
const stopTest = () => {
  if (!socket.value || socket.value.readyState !== WebSocket.OPEN) {
    ElMessage.error('WebSocket连接未建立,请稍后重试')
    return
  }

  try {
    const message = {
      type: 'stopTest'
    }
    // 确保WebSocket连接已建立
    if (socket.value && socket.value.readyState === WebSocket.OPEN) {
      socket.value.send(JSON.stringify(message))
      ElMessage.success('已发送停止命令')
    } else {
      ElMessage.error('WebSocket连接已断开,请刷新页面重试')
    }
  } catch (error) {
    ElMessage.error('发送停止命令失败: ' + (error.message || '未知错误'))
  }
}

// 刷新节点列表
const refreshWorkerList = async () => {
  refreshing.value = true
  try {
    requestWorkerList()
  } finally {
    setTimeout(() => {
      refreshing.value = false
    }, 1000)
  }
}

// 发送WebSocket消息
const sendWSMessage = (type: string, data: any) => {
  if (socket.value?.readyState === WebSocket.OPEN) {
    socket.value.send(JSON.stringify({ type, data }))
  } else {
    ElMessage.error('WebSocket未连接')
  }
}

// 节点选择处理
const handleWorkerSelection = (selection: WorkerInfo[]) => {
  form.workerNodes = selection.map(worker => worker.ip)
}

// 全选/取消全选节点
const selectAllWorkers = () => {
  if (form.workerNodes.length === onlineWorkers.value.length) {
    form.workerNodes = []
  } else {
    form.workerNodes = onlineWorkers.value.map(worker => worker.ip)
  }
}

// 状态样式
const getStatusType = (status: string) => {
  switch (status) {
    case 'online':
      return 'success'
    case 'busy':
      return 'warning'
    case 'offline':
      return 'danger'
    default:
      return 'info'
  }
}

const getCPUStatus = (usage: number) => {
  if (usage >= 90) return 'exception'
  if (usage >= 70) return 'warning'
  return 'success'
}

const getMemStatus = (usage: number) => {
  if (usage >= 90) return 'exception'
  if (usage >= 70) return 'warning'
  return 'success'
}

// 图表配置
const cpuChartOption = computed(() => ({
  tooltip: {
    trigger: 'axis'
  },
  legend: {
    data: Object.keys(cpuData.value)
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true
  },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: timePoints.value
  },
  yAxis: {
    type: 'value',
    name: 'CPU使用率(%)'
  },
  series: Object.entries(cpuData.value).map(([ip, data]) => ({
    name: ip,
    type: 'line',
    data: data
  }))
}))

const memChartOption = computed(() => ({
  tooltip: {
    trigger: 'axis'
  },
  legend: {
    data: Object.keys(memData.value)
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true
  },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: timePoints.value
  },
  yAxis: {
    type: 'value',
    name: '内存使用率(%)'
  },
  series: Object.entries(memData.value).map(([ip, data]) => ({
    name: ip,
    type: 'line',
    data: data
  }))
}))

// 生命周期钩子
onMounted(() => {
  // 建立WebSocket连接
  initWebSocket()
})

onUnmounted(() => {
  if (reconnectTimer.value) {
    clearTimeout(reconnectTimer.value)
  }
  if (socket.value) {
    socket.value.close()
  }
})

// 添加类型定义
interface AttackType {
  value: string
  label: string
  name: string
  scenes: string[]
  features: string[]
  notes: string[]
  bestPractices: {
    ports?: number[]
    targets?: string[]
    description: string
    bypassProtection: string[]
    headers?: Record<string, string>
    sslOptions?: {
      ciphers: string
      minVersion: string
      maxVersion: string
    }
  }
  effectiveness: {
    resourceConsumption: number  // 资源消耗评分(1-5)
    bypassDifficulty: number    // 绕过难度评分(1-5)
    detectionDifficulty: number // 检测难度评分(1-5)
    overall: number            // 综合效果评分(1-5)
  }
  needPort: boolean
  defaultPort?: number
}

// 修改攻击类型数组定义
const layer4Types: AttackType[] = [
  {
    value: 'tcp_flood',
    label: 'TCP Flood / TCP洪水攻击',
    name: 'TCP Flood 攻击',
    scenes: [
      'TCP服务资源耗尽',
      '高并发连接压力测试',
      '适用于所有TCP服务器'
    ],
    features: [
      '支持SYN/ACK组合攻击',
      '自动调整发包速率',
      '支持多端口并发攻击'
    ],
    notes: [
      '需要较大的系统资源',
      '建议使用多个节点',
      '注意控制并发连接数'
    ],
    bestPractices: {
      ports: [80, 443, 8080, 8443], // 最佳端口
      description: '建议同时攻击多个端口,重点是Web服务端口和管理端口',
      bypassProtection: [
        'CDN: 建议获取真实IP后进行测试',
        'WAF: 可以尝试使用非标准端口绕过',
        '防火墙: 建议使用多个节点分散攻击源'
      ]
    },
    effectiveness: {
      resourceConsumption: 4.5,
      bypassDifficulty: 3.5,
      detectionDifficulty: 2,
      overall: 4
    },
    needPort: true,
    defaultPort: 80
  },
  {
    value: 'syn_flood',
    label: 'SYN Flood / SYN洪水攻击',
    name: 'SYN Flood 攻击',
    scenes: [
      'TCP半连接资源耗尽',
      'DOS防护测试',
      '连接队列溢出测试'
    ],
    features: [
      '伪造源IP地址',
      '仅发送SYN包',
      '快速消耗连接队列'
    ],
    notes: [
      '易被SYN Cookie防护',
      '需要较大发包量',
      '建议分布式发起'
    ],
    bestPractices: {
      ports: [21, 22, 23, 25, 80, 443, 3306, 6379], // 常见服务端口
      description: '建议针对关键业务端口进行压测,如数据库、缓存等服务',
      bypassProtection: [
        'SYN Cookie: 增加并发连接数和节点数',
        'TCP Shield: 使用合法TCP标志组合',
        '限速: 控制单IP发包频率,使用更多节点'
      ]
    },
    effectiveness: {
      resourceConsumption: 4,
      bypassDifficulty: 3,
      detectionDifficulty: 2.5,
      overall: 3.5
    },
    needPort: true,
    defaultPort: 80
  },
  {
    value: 'ack_flood',
    label: 'ACK Flood / ACK确认攻击',
    name: 'ACK Flood 攻击',
    scenes: [
      '状态表资源耗尽',
      '防火墙压力测试',
      'NAT设备测试'
    ],
    features: [
      '伪造ACK包',
      '绕过SYN Cookie',
      '消耗状态表资源'
    ],
    notes: [
      '需要原始套接字权限',
      '易被启发式检测',
      '建议合理控制速率'
    ],
    effectiveness: {
      resourceConsumption: 3.5,
      bypassDifficulty: 4,
      detectionDifficulty: 3.5,
      overall: 3.5
    },
    needPort: true
  },
  {
    value: 'ntp_amp',
    label: 'NTP Amplification / NTP放大攻击',
    name: 'NTP 放大攻击',
    scenes: [
      'NTP服务器测试',
      '带宽耗尽测试',
      '反射放大攻击测试'
    ],
    features: [
      '利用monlist指令',
      '流量放大倍数高',
      '难以溯源'
    ],
    notes: [
      '需要开放的NTP服务器',
      '注意运营商管控',
      '避免滥用'
    ],
    effectiveness: {
      resourceConsumption: 5,
      bypassDifficulty: 4,
      detectionDifficulty: 3,
      overall: 4.5
    },
    needPort: true,
    defaultPort: 123
  },
  {
    value: 'ssdp_amp',
    label: 'SSDP Amplification / SSDP放大攻击',
    name: 'SSDP 放大攻击',
    scenes: [
      'SSDP服务探测',
      'UPnP设备测试',
      '带宽耗尽测试'
    ],
    features: [
      'M-SEARCH放大',
      '自动发现反射器',
      '支持IPv4/IPv6'
    ],
    notes: [
      '需要开放的SSDP设备',
      '放大倍数不稳定',
      '易被检测'
    ],
    effectiveness: {
      resourceConsumption: 4.5,
      bypassDifficulty: 3.5,
      detectionDifficulty: 3,
      overall: 4
    },
    needPort: true,
    defaultPort: 1900
  },
  {
    value: 'memcached_amp',
    label: 'Memcached Amplification / Memcached放大攻击',
    name: 'Memcached 放大攻击',
    scenes: [
      'Memcached服务测试',
      '带宽耗尽测试',
      '大规模反射测试'
    ],
    features: [
      'stats命令放大',
      '放大倍数最高',
      '支持多命令组合'
    ],
    notes: [
      '需要开放的Memcached',
      '服务器越来越少',
      '注意网络管控'
    ],
    effectiveness: {
      resourceConsumption: 5,
      bypassDifficulty: 4,
      detectionDifficulty: 3.5,
      overall: 4.5
    },
    needPort: true,
    defaultPort: 11211
  }
]

const layer7Types: AttackType[] = [
  {
    value: 'http2_ws',
    label: 'HTTP2 + WebSocket / 多路复用攻击',
    name: 'HTTP2 Stream + WebSocket 攻击',
    scenes: [
      '现代Web应用压测',
      'WebSocket长连接测试',
      'HTTP2多路复用压力'
    ],
    features: [
      'HTTP2多流并发',
      'WebSocket消息轰炸',
      '自动心跳保活'
    ],
    notes: [
      '需要目标支持HTTP2',
      '建议配合代理使用',
      '注意连接数限制'
    ],
    bestPractices: {
      targets: [
        '/api/*', // API接口
        '/ws/*',  // WebSocket接口
        '/*.php', // 动态页面
        '/*.jsp'
      ],
      description: '优先测试动态页面和接口,避免静态资源',
      bypassProtection: [
        'CDN: 使用合法User-Agent和Cookie',
        'WAF: 自定义HTTP头部和参数',
        '频率限制: 使用代理池分散请求'
      ],
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'en-US,en;q=0.5',
        'Accept-Encoding': 'gzip, deflate, br',
        'Connection': 'keep-alive',
        'Cache-Control': 'no-cache'
      }
    },
    effectiveness: {
      resourceConsumption: 4,
      bypassDifficulty: 4,
      detectionDifficulty: 3.5,
      overall: 4
    },
    needPort: false
  },
  {
    value: 'ssl_slow',
    label: 'SSL + SlowHTTP / 混合慢速攻击',
    name: 'SSL重协商 + 慢速HTTP攻击',
    scenes: [
      'HTTPS服务压测',
      'Web服务器资源耗尽',
      'SSL握手压力测试'
    ],
    features: [
      'SSL重协商消耗',
      '慢速HTTP请求',
      '组合攻击效果好'
    ],
    notes: [
      '仅适用于SSL服务',
      '需要较多连接数',
      '容易触发WAF'
    ],
    bestPractices: {
      targets: [
        'https://*.com/login',  // 登录接口
        'https://*.com/upload', // 上传接口
        'https://*.com/search'  // 搜索接口
      ],
      description: '针对HTTPS的动态接口进行测试,特别是计算密集型接口',
      bypassProtection: [
        'CDN: 模拟真实浏览器行为',
        'WAF: 使用合法SSL参数',
        '超时限制: 动态调整请求间隔'
      ],
      sslOptions: {
        ciphers: 'ECDHE-RSA-AES128-GCM-SHA256:...',
        minVersion: 'TLS1.2',
        maxVersion: 'TLS1.3'
      }
    },
    effectiveness: {
      resourceConsumption: 4.5,
      bypassDifficulty: 3.5,
      detectionDifficulty: 3,
      overall: 4
    },
    needPort: false
  },
  {
    value: 'slowloris',
    label: 'Slowloris / 慢速头部攻击',
    name: 'Slowloris 攻击',
    scenes: [
      'Web服务器连接耗尽',
      'Apache服务器测试',
      '连接资源压测'
    ],
    features: [
      '慢速发送头部',
      '保持连接不释放',
      '低带宽高效率'
    ],
    notes: [
      '对新版本Apache效果差',
      '易被超时机制防御',
      '需要大量连接'
    ],
    bestPractices: {
      targets: [
        '/login', 
        '/admin',
        '/upload',
        '/*.php'
      ],
      description: '针对需要长时间保持连接的接口进行测试',
      bypassProtection: [
        'CDN: 使用真实浏览器UA和Cookie',
        'WAF: 控制请求头发送速率',
        '超时: 动态调整保活间隔'
      ],
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...',
        'Keep-Alive': 'timeout=60, max=1000',
        'Connection': 'keep-alive'
      }
    },
    effectiveness: {
      resourceConsumption: 3.5,
      bypassDifficulty: 4,
      detectionDifficulty: 4,
      overall: 3.5
    },
    needPort: false
  },
  {
    value: 'rudy',
    label: 'R.U.D.Y / 慢速POST攻击',
    name: 'R.U.D.Y 攻击',
    scenes: [
      'POST请求处理测试',
      '应用服务器压测',
      '连接资源耗尽'
    ],
    features: [
      '慢速发送POST数据',
      '模拟正常上传',
      '难以区分恶意请求'
    ],
    notes: [
      '需要目标支持POST',
      '注意超时配置',
      '建议使用代理池'
    ],
    bestPractices: {
      targets: [
        '/upload',
        '/import',
        '/profile/avatar',
        '/*upload*.php'
      ],
      description: '针对文件上传和数据提交接口进行测试',
      bypassProtection: [
        'CDN: 模拟正常上传行为',
        'WAF: 使用合法Content-Type',
        '超时: 保持稳定的发送速率'
      ],
      headers: {
        'Content-Type': 'multipart/form-data; boundary=...',
        'Content-Length': '1000000000'
      }
    },
    effectiveness: {
      resourceConsumption: 4,
      bypassDifficulty: 4.5,
      detectionDifficulty: 4,
      overall: 4
    },
    needPort: false
  },
  {
    value: 'slow_read',
    label: 'Slow Read / 慢速读取攻击',
    name: 'Slow Read 攻击',
    scenes: [
      'Web服务响应测试',
      '服务器发送缓冲区测试',
      '连接资源压测'
    ],
    features: [
      '慢速读取响应',
      '调整TCP窗口大小',
      '保持连接不释放'
    ],
    notes: [
      '需要服务器支持长连接',
      '易被带宽控制防御',
      '效果依赖网络状况'
    ],
    effectiveness: {
      resourceConsumption: 3.5,
      bypassDifficulty: 3.5,
      detectionDifficulty: 3.5,
      overall: 3.5
    },
    needPort: false
  },
  {
    value: 'slow_post',
    label: 'Slow POST / 慢速提交攻击',
    name: 'Slow POST 攻击',
    scenes: [
      'POST请求处理测试',
      '应用服务器资源测试',
      '连接超时测试'
    ],
    features: [
      '慢速分块提交',
      '模拟大文件上传',
      '自动维持连接'
    ],
    notes: [
      '需要支持分块传输',
      '注意Content-Length',
      '建议使用代理'
    ],
    effectiveness: {
      resourceConsumption: 4,
      bypassDifficulty: 4,
      detectionDifficulty: 3.5,
      overall: 4
    },
    needPort: false
  }
]

// 攻击类型变化处理
const handleTestTypeChange = () => {
  // 重置表单数据
  form.targetIp = ''
  form.targetUrl = ''
  form.layer4Type = 'syn_flood'
  form.layer7Type = 'http_flood'
  form.port = ''
  form.proxyList = []
}

const handleAttackTypeChange = () => {
  // 重置表单数据
  form.targetIp = ''
  form.targetUrl = ''
  form.port = ''
  form.proxyList = []
}

const handleProxyFileChange = (event: any) => {
  // 处理代理文件上传逻辑
  if (event.file) {
    form.proxyList = event.file.raw.map((f: any) => f.name)
  }
}

// 格式化流量
const formatTraffic = (bytes: number) => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 格式化速率
const formatSpeed = (bytesPerSecond: number) => {
  return formatTraffic(bytesPerSecond) + '/s'
}

// 计算流量百分比
const getTrafficPercentage = (traffic: number) => {
  if (!totalTraffic.value || !traffic) return 0
  return Math.min((traffic / totalTraffic.value) * 100, 100)
}

// 流量趋势图配置
const trafficChartOption = computed(() => ({
  tooltip: {
    trigger: 'axis',
    formatter: (params: any) => {
      const time = params[0].name
      let html = `${time}<br/>`
      params.forEach((param: any) => {
        html += `${param.seriesName}: ${formatTraffic(param.value)}<br/>`
      })
      return html
    }
  },
  legend: {
    data: workerTraffic.value.map(w => w.ip)
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true
  },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: timePoints.value
  },
  yAxis: {
    type: 'value',
    axisLabel: {
      formatter: (value: number) => formatTraffic(value)
    }
  },
  series: workerTraffic.value.map(worker => ({
    name: worker.ip,
    type: 'line',
    smooth: true,
    data: trafficData.value[worker.ip] || []
  }))
}))

// 更新流量统计的方法
const updateTrafficStats = (data: any) => {
  // 更新总流量
  totalTraffic.value = data.totalTraffic || 0
  stats.value.totalTraffic = data.totalTraffic || 0
  stats.value.totalRequests = data.totalRequests || 0
  stats.value.avgLatency = data.avgLatency || 0
  
  // 更新节点流量数据
  if (data.workerTraffic) {
    workerTraffic.value = Object.entries(data.workerTraffic).map(([ip, stats]: [string, any]) => ({
      ip,
      traffic: stats.traffic || 0,
      speed: stats.speed || 0,
      packets: stats.packets || 0
    }))
  }

  // 更新流量趋势数据
  const now = new Date().toLocaleTimeString('zh-CN', { hour12: false })
  if (!timePoints.value.includes(now)) {
    timePoints.value.push(now)
    if (timePoints.value.length > 30) {
      timePoints.value.shift()
    }
  }

  // 更新每个节点的流量数据
  workerTraffic.value.forEach(worker => {
    if (!trafficData.value[worker.ip]) {
      trafficData.value[worker.ip] = []
    }
    trafficData.value[worker.ip].push(worker.traffic)
    if (trafficData.value[worker.ip].length > 30) {
      trafficData.value[worker.ip].shift()
    }
  })
}

// 当前选中的攻击类型信息
const currentAttackInfo = computed(() => {
  if (!form.testType) return null
  const attackType = form.testType === 'layer4' ? form.layer4Type : form.layer7Type
  const types = form.testType === 'layer4' ? layer4Types : layer7Types
  return types.find(t => t.value === attackType)
})

// 使用默认端口
const useDefaultPort = () => {
  if (currentAttackInfo.value?.defaultPort) {
    form.port = currentAttackInfo.value.defaultPort.toString()
  }
}

// 端口输入框获得焦点时提示
const handlePortFocus = () => {
  if (currentAttackInfo.value?.defaultPort) {
    ElMessage.info(`当前攻击类型的默认端口为: ${currentAttackInfo.value.defaultPort}`)
  }
}

// 使用推荐端口
const usePort = (port: number) => {
  form.port = port.toString()
}

// Layer4 攻击评分
const layer4Effectiveness = {
  tcp_flood: {
    resourceConsumption: 4.5,
    bypassDifficulty: 3.5,
    detectionDifficulty: 2,
    overall: 4
  },
  syn_flood: {
    resourceConsumption: 4,
    bypassDifficulty: 3,
    detectionDifficulty: 2.5,
    overall: 3.5
  },
  ack_flood: {
    resourceConsumption: 3.5,
    bypassDifficulty: 4,
    detectionDifficulty: 3.5,
    overall: 3.5
  },
  ntp_amp: {
    resourceConsumption: 5,
    bypassDifficulty: 4,
    detectionDifficulty: 3,
    overall: 4.5
  },
  ssdp_amp: {
    resourceConsumption: 4.5,
    bypassDifficulty: 3.5,
    detectionDifficulty: 3,
    overall: 4
  },
  memcached_amp: {
    resourceConsumption: 5,
    bypassDifficulty: 4,
    detectionDifficulty: 3.5,
    overall: 4.5
  }
}

// Layer7 攻击评分
const layer7Effectiveness = {
  http2_ws: {
    resourceConsumption: 4,
    bypassDifficulty: 4,
    detectionDifficulty: 3.5,
    overall: 4
  },
  ssl_slow: {
    resourceConsumption: 4.5,
    bypassDifficulty: 3.5,
    detectionDifficulty: 3,
    overall: 4
  },
  slowloris: {
    resourceConsumption: 3.5,
    bypassDifficulty: 4,
    detectionDifficulty: 4,
    overall: 3.5
  },
  rudy: {
    resourceConsumption: 4,
    bypassDifficulty: 4.5,
    detectionDifficulty: 4,
    overall: 4
  },
  slow_read: {
    resourceConsumption: 3.5,
    bypassDifficulty: 3.5,
    detectionDifficulty: 3.5,
    overall: 3.5
  },
  slow_post: {
    resourceConsumption: 4,
    bypassDifficulty: 4,
    detectionDifficulty: 3.5,
    overall: 4
  }
}

// 更新统计数据
const updateStats = () => {
  if (!onlineWorkers.value.length) return
  
  // 计算平均延迟
  const totalLatency = onlineWorkers.value.reduce((sum, worker) => sum + (worker.latency || 0), 0)
  avgLatency.value = Math.round(totalLatency / onlineWorkers.value.length)
  
  // 统计总请求数和流量
  totalRequests.value = onlineWorkers.value.reduce((sum, worker) => sum + (worker.requests || 0), 0)
  totalTraffic.value = onlineWorkers.value.reduce((sum, worker) => sum + (worker.traffic || 0), 0)
}

// 格式化时间戳
const formatTimestamp = (timestamp: number) => {
  if (!timestamp) return '-'
  return formatDateTime(new Date(timestamp))
}

// 获取在线节点数
const getOnlineCount = () => {
  return onlineWorkers.value.filter(w => w.status === 'online').length
}

// 获取总节点数
const getTotalCount = () => {
  return onlineWorkers.value.length
}

// 格式化字节大小
const formatBytes = (bytes: number) => {
  if (!bytes) return '-'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
</script>

<style lang="scss" scoped>


// 移动端适配
@media screen and (width <= 768px) {
  .el-row {
    display: block !important;  // 移除flex布局
  }
  
  .el-col {
    width: 100% !important;    // 列占满宽度
    margin-bottom: 16px;
  }
  
  .status-cards {
    display: grid !important;
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 10px;
    margin-bottom: 16px;
    
    .status-card {
      display: flex !important;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      height: 80px;
      padding: 10px;
      margin: 0;
      box-sizing: border-box;
      
      .status-value {
        display: block;
        margin: 4px 0;
        font-size: 18px;
        font-weight: bold;
        color: var(--el-color-primary);
        
        .success {
          color: var(--el-color-success);
        }
        
        .text-gray {
          margin: 0 4px;
          color: #909399;
        }
      }
      
      .status-label {
        font-size: 14px;
        color: #909399;
        text-align: center;
      }
    }
  }
  
  .worker-table {
    margin-top: 16px;
    
    :deep(.el-table) {
      width: 100%;
      
      .el-table__body-wrapper {
        max-height: calc(100vh - 600px);
        min-height: 300px;
      }
    }
  }
}

.stress-test-container {
  padding: 20px;
  
  .el-card {
    display: flex;
    height: 420px;
    flex-direction: column;
    
    :deep(.el-card__body) {
      padding: 0;
      overflow: hidden;
    }
  }

  .control-panel, .info-panel {
    display: flex;
    flex-direction: column;

    :deep(.el-card__body) {
      flex: 1;
      overflow-y: auto;
    }
  }

  .control-panel {
    .attack-option {
  display: flex;
  justify-content: space-between;
  align-items: center;
    }
  }

  .info-panel {
    .attack-info {
      height: 100%;
      padding: 12px 20px 12px 24px;
      overflow-y: auto;
      
      &::-webkit-scrollbar {
        width: 6px;
      }
      
      &::-webkit-scrollbar-thumb {
        background-color: #909399;
        border-radius: 3px;
      }
      
      &::-webkit-scrollbar-track {
        background-color: #f4f4f5;
      }

      .info-section {
        margin-bottom: 12px;

        h4 {
          display: flex;
          align-items: center;
          gap: 6px;
          margin-bottom: 8px;
          font-size: 15px;
          color: var(--el-color-primary);

          .el-icon {
            font-size: 16px;
          }
        }

        .scene-tags {
          display: flex;
          flex-wrap: wrap;
          gap: 6px;
          padding-left: 4px;

          .scene-tag {
            padding: 2px 6px;
            margin: 0;
            font-size: 13px;
          }
        }

        .feature-list,
        .warning-list {
          padding: 0;
          margin: 0;
          list-style: none;

          li {
            position: relative;
            padding-left: 16px;
            margin-bottom: 6px;
            font-size: 14px;
            line-height: 1.5;
          }
        }

        .warning-list li::before {
          background-color: var(--el-color-warning);
        }
      }

      .best-ports {
        margin: 8px 0;
        
        h5 {
          margin-bottom: 8px;
          font-size: 13px;
          color: #606266;
        }
        
        .port-tags {
          display: flex;
          flex-wrap: wrap;
          gap: 6px;
          
          .port-tag {
            font-size: 12px;
            cursor: pointer;
          }
        }
      }

      .best-targets {
        .target-list {
          padding-left: 0;
          list-style: none;
          
          li {
            padding: 4px 0;
            font-size: 13px;
          }
        }
      }

      .practice-desc {
        padding: 6px 8px;
        margin: 8px 0 8px 4px;
        font-size: 14px;
      }

      .bypass-list {
        li {
          margin-bottom: 8px;
          font-size: 13px;
        }
      }

      .headers-preview {
        pre {
          padding: 8px 12px;
          margin-left: 4px;
          overflow: auto;
          background: #f5f7fa;
          border-radius: 4px;
          
          code {
            font-size: 13px;
          }
        }
      }
    }
  }
}

.status-cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  margin-bottom: 20px;
  
  .status-card {
    display: flex;
    height: 100px;
    text-align: center;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    
    .status-value {
      margin: 6px 0;
      font-size: 20px;
      font-weight: bold;
      color: var(--el-color-primary);
      
      .success {
        color: var(--el-color-success);
      }
      
      .text-gray {
        margin: 0 4px;
        color: #909399;
      }
    }
    
    .status-label {
      font-size: 14px;
      color: #909399;
    }
  }
}

.cursor-pointer {
  color: var(--el-color-primary);
  cursor: pointer;
  
  &:hover {
    opacity: 0.8;
  }
}

.effectiveness-preview {
  .el-descriptions {
    margin: 15px 0;
    
    .el-rate {
      display: inline-block;
    }
  }
}

.defense-tips {
  padding: 10px;
  background: #f5f7fa;
  border-radius: 4px;
  
  p {
    margin: 5px 0;
    color: #606266;
    
    &::before {
      margin-right: 8px;
      color: var(--el-color-primary);
      content: '•';
    }
  }
}

.form-container,
.monitor-container {
  height: auto;
  max-height: calc(100vh - 160px);
  padding: 15px;
  overflow-y: auto;
}

.status-card {
  height: auto;
  min-height: auto;
  margin: 0;
  
  :deep(.el-card__header) {
    padding: 6px 8px;
    font-size: 13px;
  }
  
  :deep(.el-card__body) {
    padding: 10px 8px;
  }

  .status-value {
    margin: 8px 0;
    font-size: 20px;
  font-weight: bold;
  }
}

.worker-table {
  margin-top: 16px;
  
  :deep(.el-table) {
    width: 100%;
    border-radius: 8px;
    
    .el-table__header-wrapper {
      th {
        padding: 12px 0;
        font-weight: 600;
        background-color: var(--el-fill-color-light);
      }
    }
    
    .el-table__body-wrapper {
      td {
        padding: 12px 0;
      }
    }
    
    .el-table__row {
      &:hover {
        td {
          background-color: var(--el-fill-color-lighter);
        }
      }
    }
  }
}

.attack-stats, .traffic-stats {
  font-size: 12px;
  line-height: 1.5;
  
  div {
    display: flex;
    justify-content: space-between;
    color: var(--el-text-color-regular);
    
    &:not(:last-child) {
      margin-bottom: 2px;
    }
  }
}

.progress-bar {
  :deep(.el-progress-bar__outer) {
    background-color: var(--el-fill-color-light);
  }
  
  :deep(.el-progress-bar__inner) {
    transition: all 0.3s ease;
  }
  
  .progress-text {
    position: absolute;
    top: 50%;
    left: 50%;
    font-size: 12px;
    font-weight: 500;
    color: #fff;
    text-shadow: 0 0 2px rgb(0 0 0 / 20%);
    transform: translate(-50%, -50%);
  }
}
</style> 